home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Tk / unix / tkUnixDraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-31  |  4.8 KB  |  172 lines

  1. /* 
  2.  * tkUnixDraw.c --
  3.  *
  4.  *    This file contains X specific drawing routines.
  5.  *
  6.  * Copyright (c) 1995 Sun Microsystems, Inc.
  7.  *
  8.  * See the file "license.terms" for information on usage and redistribution
  9.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  10.  *
  11.  * SCCS: @(#) tkUnixDraw.c 1.7 96/02/15 18:55:26
  12.  */
  13.  
  14. #include "tkPort.h"
  15. #include "tkInt.h"
  16.  
  17. /*
  18.  * The following structure is used to pass information to
  19.  * ScrollRestrictProc from TkScrollWindow.
  20.  */
  21.  
  22. typedef struct ScrollInfo {
  23.     int done;            /* Flag is 0 until filtering is done. */
  24.     Display *display;        /* Display to filter. */
  25.     Window window;        /* Window to filter. */
  26.     TkRegion region;        /* Region into which damage is accumulated. */
  27.     int dx, dy;            /* Amount by which window was shifted. */
  28. } ScrollInfo;
  29.  
  30. /*
  31.  * Forward declarations for procedures declared later in this file:
  32.  */
  33.  
  34. static Tk_RestrictAction    ScrollRestrictProc _ANSI_ARGS_((
  35.                         ClientData arg, XEvent *eventPtr));
  36.  
  37. /*
  38.  *----------------------------------------------------------------------
  39.  *
  40.  * TkScrollWindow --
  41.  *
  42.  *    Scroll a rectangle of the specified window and accumulate
  43.  *    damage information in the specified Region.
  44.  *
  45.  * Results:
  46.  *    Returns 0 if no damage additional damage was generated.  Sets
  47.  *    damageRgn to contain the damaged areas and returns 1 if
  48.  *    GraphicsExpose events were detected.
  49.  *
  50.  * Side effects:
  51.  *    Scrolls the bits in the window and enters the event loop
  52.  *    looking for damage events.
  53.  *
  54.  *----------------------------------------------------------------------
  55.  */
  56.  
  57. int
  58. TkScrollWindow(tkwin, gc, x, y, width, height, dx, dy, damageRgn)
  59.     Tk_Window tkwin;        /* The window to be scrolled. */
  60.     GC gc;            /* GC for window to be scrolled. */
  61.     int x, y, width, height;    /* Position rectangle to be scrolled. */
  62.     int dx, dy;            /* Distance rectangle should be moved. */
  63.     TkRegion damageRgn;        /* Region to accumulate damage in. */
  64. {
  65.     Tk_RestrictProc *oldProc;
  66.     ClientData oldArg, dummy;
  67.     ScrollInfo info;
  68.     
  69.     XCopyArea(Tk_Display(tkwin), Tk_WindowId(tkwin), Tk_WindowId(tkwin), gc,
  70.         x, y, (unsigned int) width, (unsigned int) height, x + dx, y + dy);
  71.  
  72.     info.done = 0;
  73.     info.window = Tk_WindowId(tkwin);
  74.     info.display = Tk_Display(tkwin);
  75.     info.region = damageRgn;
  76.     info.dx = dx;
  77.     info.dy = dy;
  78.  
  79.     /*
  80.      * Sync the event stream so all of the expose events will be on the
  81.      * X event queue before we start filtering.  This avoids busy waiting
  82.      * while we filter events.
  83.      */
  84.  
  85.     XSync(info.display, False);
  86.     oldProc = Tk_RestrictEvents(ScrollRestrictProc, (ClientData) &info,
  87.         &oldArg);
  88.     while (!info.done) {
  89.     Tcl_DoOneEvent(TCL_WINDOW_EVENTS|TCL_DONT_WAIT);
  90.     }
  91.     Tk_RestrictEvents(oldProc, oldArg, &dummy);
  92.  
  93.     return XEmptyRegion((Region) damageRgn) ? 0 : 1;
  94. }
  95.  
  96. /*
  97.  *----------------------------------------------------------------------
  98.  *
  99.  * ScrollRestrictProc --
  100.  *
  101.  *    A Tk_RestrictProc used by TkScrollWindow to gather up Expose
  102.  *    information into a single damage region.  It accumulates damage
  103.  *    events on the specified window until a NoExpose or the last
  104.  *    GraphicsExpose event is detected.
  105.  *
  106.  * Results:
  107.  *    None.
  108.  *
  109.  * Side effects:
  110.  *    Discards Expose events after accumulating damage information
  111.  *    for a particular window.
  112.  *
  113.  *----------------------------------------------------------------------
  114.  */
  115.  
  116. static Tk_RestrictAction
  117. ScrollRestrictProc(arg, eventPtr)
  118.     ClientData arg;
  119.     XEvent *eventPtr;
  120. {
  121.     ScrollInfo *info = (ScrollInfo *) arg;
  122.     XRectangle rect;
  123.  
  124.     /*
  125.      * Defer events which aren't for the specified window.
  126.      */
  127.  
  128.     if (info->done || (eventPtr->xany.display != info->display)
  129.         || (eventPtr->xany.window != info->window)) {
  130.     return TK_DEFER_EVENT;
  131.     }
  132.  
  133.     if (eventPtr->type == NoExpose) {
  134.     info->done = 1;
  135.     } else if (eventPtr->type == GraphicsExpose) {
  136.     rect.x = eventPtr->xgraphicsexpose.x;
  137.     rect.y = eventPtr->xgraphicsexpose.y;
  138.     rect.width = eventPtr->xgraphicsexpose.width;
  139.     rect.height = eventPtr->xgraphicsexpose.height;
  140.     XUnionRectWithRegion(&rect, (Region) info->region,
  141.         (Region) info->region);
  142.  
  143.     if (eventPtr->xgraphicsexpose.count == 0) {
  144.         info->done = 1;
  145.     }
  146.     } else if (eventPtr->type == Expose) {
  147.  
  148.     /*
  149.      * This case is tricky.  This event was already queued before
  150.      * the XCopyArea was issued.  If this area overlaps the area
  151.      * being copied, then some of the copied area may be invalid.
  152.      * The easiest way to handle this case is to mark both the
  153.      * original area and the shifted area as damaged.
  154.      */
  155.  
  156.     rect.x = eventPtr->xexpose.x;
  157.     rect.y = eventPtr->xexpose.y;
  158.     rect.width = eventPtr->xexpose.width;
  159.     rect.height = eventPtr->xexpose.height;
  160.     XUnionRectWithRegion(&rect, (Region) info->region,
  161.         (Region) info->region);
  162.     rect.x += info->dx;
  163.     rect.y += info->dy;
  164.     XUnionRectWithRegion(&rect, (Region) info->region,
  165.         (Region) info->region);
  166.     } else {
  167.     return TK_DEFER_EVENT;
  168.     }
  169.     return TK_DISCARD_EVENT;
  170. }
  171.  
  172.